home *** CD-ROM | disk | FTP | other *** search
/ Game.EXE 2001 January / Game.EXE_01_2001.iso / demos / Blade of Darkness / data1.cab / Program_Executable_Files / Lib / Enm_Def.py < prev    next >
Encoding:
Text File  |  2000-11-16  |  65.8 KB  |  2,035 lines

  1. import Bladex
  2. import whrandom
  3. import AuxTran
  4. import ScorerActions
  5. import Actions
  6. import Reference
  7. import Basic_Funcs
  8. import Combat
  9. import CharStats
  10. import copy
  11. import whrandom
  12. #import BDAux
  13. import Damage
  14. import Stars
  15. import DMusic
  16. import GameStateAux
  17. #if Reference.DEBUG_INFO == 1:
  18. import pdb    
  19.  
  20. DEBUG_SOUNDS=0
  21. ##################################################################################
  22. #  E V E N T S
  23.  
  24.     # We see the enemy ["SeeFunc"]
  25.     # 
  26.     # We have lost the enemy ["DelayNoSeenFunc"]
  27.     # We have entered an illegal area ["NoAllowedAreaFunc"]
  28.     # Our enemy (who we are chasing) enters an illegal area) ["EnemyNoAllowedAreaFunc"]
  29.     # We are hurt ["ImHurtFunc"]
  30.     # We die ["ImDeadFunc"]
  31.     # Our enemy dies ["EnemyDeadFunc"]
  32.     # An animation ends ["AnmEndedFunc"]
  33.     # We enter close weapon range with our enemy ["EnterCloseFunc"]
  34.     # We enter far weapon range (bows/crossbows) ["EnterLargeFunc"]
  35.     # We enter our primary action area  ["EnterPrimaryAAFunc"]
  36.     # We enter our secondary action area["EnterSecondaryAAFunc"]
  37.     # Another character entity sees his enemy ["CharSeeingEnemyFunc"]
  38.     # Executed a combo for the first time ["NewComboFunc"]
  39.     # Engage/disengage combat mode ["ToggleCombatFunc"]
  40.  
  41. ##################################################################################
  42. #
  43. #
  44. # Pseudo defines
  45. #
  46. #
  47. ##################################################################################
  48.  
  49. #
  50. # Twinkle FX for several kinds of objects
  51. #
  52. TwinkleObjs = ["Gema"]
  53.  
  54. THROWNHURTTIME_GAP=45
  55. #
  56. #Several sets of values needed for the SetAnmFlags() and SetTmpAnmFlags() methods
  57. #
  58.  
  59. #"bng_mov" parameter
  60. BM_IDC=0
  61. BM_NONE=1
  62. BM_XYZ=2
  63. BM_XZ=3
  64. BM_2ANM=4
  65. BM_SCRIPT=5
  66.  
  67. #"headf" parameter
  68. HEADF_ENG=0
  69. HEADF_ANM=1
  70. HEADF_ANM2SEE=2
  71. HEADF_ANM2ENG=3
  72.  
  73.  
  74.  
  75. #
  76. #Values returned by AstarState
  77. #
  78. ASTAR_THINKING=0
  79. ASTAR_NOSOLVED=1
  80. ASTAR_SOLVED=2
  81. ASTAR_RECALCULATING=3
  82.  
  83. #
  84. # Boolean value
  85. #
  86. TRUE = 1==1
  87. FALSE = not TRUE
  88.  
  89.  
  90. #
  91. #NOTE :Values returned by StatR() AND StatL() are declared in Actions.py
  92. #
  93.     
  94.  
  95. #
  96. #Values returned by the Wuea("WaitUntilEnfofAnimation")
  97. #
  98. WUEA_NONE=0    #It does not have to wait (relax , jog or similars)
  99. WUEA_WAIT=1    #It has to wait , and is waiting to end it
  100. WUEA_ENDED=2   #It has to wait , and it has just ended
  101.  
  102. #
  103. #Values returned by GetActionMode() 
  104. #
  105. ROUTE_WATCH=0  #Watch mode
  106. ROUTE_BAY=1    #Performing a bay route
  107. ROUTE_CHASE=2  #Chase a character
  108. ROUTE_SINGLE=3 #Following a single route (going to just a point)
  109. ROUTE_BOWING=4 #Bowing (OR trying to bow) an enemy
  110. ##################################################################################
  111.  
  112. # Comparison results for sorting
  113. CHOOSE_FIRST  = -1
  114. CHOOSE_SECOND =  1
  115. CHOOSE_EITHER =  0
  116.  
  117. # yeah! cool sounds 
  118. new_key_sound = Bladex.CreateSound('..\\..\\Sounds\\Manipulado-llave2.wav', 'NewKeySound')
  119. new_key_sound.Volume=1
  120. new_key_sound.MinDistance=10000
  121. new_key_sound.MaxDistance=20000
  122.  
  123. ##################################################################################
  124. #
  125. #
  126. # Sorting enemy functions
  127. #
  128. #
  129. ##################################################################################
  130.  
  131. def ChooseNearest (entity1name, entity2name):
  132.     p1 = Bladex.GetEntity(entity1name)
  133.     p2 = Bladex.GetEntity(entity2name)
  134.     if not p1 and not p2:
  135.         return CHOOSE_EITHER
  136.     elif not p1:
  137.         return CHOOSE_SECOND
  138.     elif not p2:
  139.         return CHOOSE_FIRST
  140.  
  141.     if p1.Life <= 0 and p2.Life <= 0:
  142.         return CHOOSE_EITHER
  143.     elif p1.Life <= 0:
  144.         return CHOOSE_SECOND
  145.     elif p2.Life <= 0:
  146.         return CHOOSE_FIRST
  147.  
  148.  
  149.     # If it just comes down to distance, group leaders may order others before them
  150.     if p1.Data.group_leader:
  151.         return CHOOSE_SECOND
  152.     elif p2.Data.group_leader:
  153.         return CHOOSE_FIRST
  154.  
  155.     enemy=Bladex.GetEntity(p1.GetEnemyName())
  156.     if not enemy:
  157.         return CHOOSE_EITHER
  158.  
  159.     val = enemy.SQDistance2(p1) - enemy.SQDistance2(p2)
  160.  
  161.     if val < 0:
  162.         return CHOOSE_FIRST
  163.     elif val > 0:
  164.         return CHOOSE_SECOND
  165.     else:
  166.         return CHOOSE_EITHER
  167.  
  168. def ChooseFurthest (entity1name, entity2name):
  169.     p1 = Bladex.GetEntity(entity1name)
  170.     p2 = Bladex.GetEntity(entity2name)
  171.     if not p1 and not p2:
  172.         return CHOOSE_EITHER
  173.     elif not p1:
  174.         return CHOOSE_SECOND
  175.     elif not p2:
  176.         return CHOOSE_FIRST
  177.  
  178.     if p1.Life <= 0 and p2.Life <= 0:
  179.         return CHOOSE_EITHER
  180.     elif p1.Life <= 0:
  181.         return CHOOSE_SECOND
  182.     elif p2.Life <= 0:
  183.         return CHOOSE_FIRST
  184.  
  185.     # If it just comes down to distance, group leaders may order others before them
  186.     if p1.Data.group_leader:
  187.         return CHOOSE_SECOND
  188.     elif p2.Data.group_leader:
  189.         return CHOOSE_FIRST
  190.  
  191.     enemy=Bladex.GetEntity(p1.GetEnemyName())
  192.     if not enemy:
  193.         return CHOOSE_EITHER
  194.  
  195.     val = enemy.SQDistance2(p1) - enemy.SQDistance2(p2)
  196.  
  197.     if val < 0:
  198.         return CHOOSE_SECOND
  199.     elif val > 0:
  200.         return CHOOSE_FIRST
  201.     else:
  202.         return CHOOSE_EITHER
  203.  
  204.  
  205. def ChooseMostLife (entity1name, entity2name):
  206.     p1 = Bladex.GetEntity(entity1name)
  207.     p2 = Bladex.GetEntity(entity2name)
  208.  
  209.     if not p1 and not p2:
  210.         return CHOOSE_EITHER
  211.     elif not p1:
  212.         return CHOOSE_SECOND
  213.     elif not p2:
  214.         return CHOOSE_FIRST
  215.  
  216.     if p1.Life <= 0 and p2.Life <= 0:
  217.         return CHOOSE_EITHER                          
  218.     elif p1.Life <= 0:
  219.         return CHOOSE_SECOND
  220.     elif p2.Life <= 0:
  221.         return CHOOSE_FIRST
  222.     
  223.     l1 = p1.Life
  224.     l2 = p2.Life
  225.     val = l2 - l1
  226.     if val < 0:
  227.         return CHOOSE_FIRST
  228.     elif val > 0:
  229.         return CHOOSE_SECOND
  230.     else:
  231.         return ChooseNearest (entity1name, entity2name)
  232.  
  233. def ChooseFighter (entity1name, entity2name):
  234.     p1 = Bladex.GetEntity(entity1name)
  235.     p2 = Bladex.GetEntity(entity2name)
  236.  
  237.     if not p1 and not p2:
  238.         return CHOOSE_EITHER
  239.     elif not p1:
  240.         return CHOOSE_SECOND
  241.     elif not p2:
  242.         return CHOOSE_FIRST
  243.  
  244.     if p1.Life <= 0 and p2.Life <= 0:
  245.         return CHOOSE_EITHER                          
  246.     elif p1.Life <= 0:
  247.         return CHOOSE_SECOND
  248.     elif p2.Life <= 0:
  249.         return CHOOSE_FIRST
  250.  
  251.     enemy=Bladex.GetEntity(p1.GetEnemyName())
  252.  
  253.     if not p1.InCombat: 
  254.         if not p2.InCombat:
  255.             # Neither are in combat, just choose the closest
  256.             return ChooseNearest (entity1name, entity2name)
  257.         # Second entity is only one in combat
  258.         return CHOOSE_SECOND
  259.     elif not p2.InCombat:
  260.         # First entity is only one in combat
  261.         return CHOOSE_FIRST
  262.  
  263.     # This far means both are in combat
  264.     if not p1.CanISee(enemy):
  265.         if not p2.CanISee(enemy):
  266.             # Neither can see the enemy, but both are in combat, 
  267.             # choose the one with most life
  268.             return ChooseMostLife (entity1name, entity2name)
  269.         # Second entity is only one to see the enemy
  270.         return CHOOSE_SECOND
  271.  
  272.     elif not p2.CanISee(enemy):
  273.         # First entity is only one to see the enemy
  274.         return CHOOSE_FIRST
  275.  
  276.     # This far means both are in combat and both can see the enemy
  277.     return ChooseMostLife (entity1name, entity2name)
  278.  
  279. def ChooseLeaderOutOfCombat (entity1name, entity2name):
  280.     p1 = Bladex.GetEntity(entity1name)
  281.     p2 = Bladex.GetEntity(entity2name)
  282.  
  283.     # Best to see the other to give them orders
  284.     if p1.CanISee(p2):
  285.         if not p2.CanISee(p1):
  286.             return CHOOSE_FIRST
  287.     elif p2.CanISee(p1):
  288.         return CHOOSE_SECOND
  289.  
  290.     # Best to see the enemy next
  291.     enemy=Bladex.GetEntity(p1.GetEnemyName())
  292.     if p1.CanISee(enemy):
  293.         if not p2.CanISee(enemy):
  294.             return CHOOSE_FIRST
  295.     elif p2.CanISee(enemy):
  296.         return CHOOSE_SECOND
  297.     
  298.     # Both or neither can see the other, 
  299.     # Both or neither can see the enemy, 
  300.     # Just choose the furthest from the enemy, 
  301.     # to order the other into combat more easily
  302.     return ChooseFurthest (entity1name, entity2name)
  303.  
  304.  
  305. def ChooseLeader (entity1name, entity2name):
  306.     p1 = Bladex.GetEntity(entity1name)
  307.     p2 = Bladex.GetEntity(entity2name)
  308.  
  309.     if not p1 and not p2:
  310.         return CHOOSE_EITHER
  311.     elif not p1:
  312.         return CHOOSE_SECOND
  313.     elif not p2:
  314.         return CHOOSE_FIRST
  315.  
  316.     if p1.Life <= 0 and p2.Life <= 0:
  317.         return CHOOSE_EITHER                          
  318.     elif p1.Life <= 0:
  319.         return CHOOSE_SECOND
  320.     elif p2.Life <= 0:
  321.         return CHOOSE_FIRST
  322.  
  323.     enemy=Bladex.GetEntity(p1.GetEnemyName())
  324.  
  325.     if p1.Data.group_fighter:
  326.         if p2.InCombat or (p2.CanISee(enemy) and p2.GetActionMode()==ROUTE_CHASE and p2.AstarState==ASTAR_SOLVED):
  327.             return CHOOSE_SECOND
  328.         # Fighter would put himself before 
  329.         return CHOOSE_FIRST
  330.  
  331.     elif p2.Data.group_fighter:
  332.         if p1.InCombat or (p1.CanISee(enemy) and p1.GetActionMode()==ROUTE_CHASE and p1.AstarState==ASTAR_SOLVED):
  333.             return CHOOSE_FIRST
  334.         # Fighter would put himself before 
  335.         return CHOOSE_SECOND
  336.  
  337.     # This far means neither are group fighters
  338.     if not p1.InCombat: 
  339.         if not p2.InCombat:
  340.             return ChooseLeaderOutOfCombat (entity1name, entity2name)
  341.         # Second entity is only one in combat
  342.         return CHOOSE_SECOND
  343.     elif not p2.InCombat:
  344.         # First entity is only one in combat
  345.         return CHOOSE_FIRST
  346.  
  347.     # This far means neither are group fighters and both are in combat
  348.     if not p1.CanISee(enemy):
  349.         if not p2.CanISee(enemy):
  350.             # Neither can see the enemy, but both are in combat, 
  351.             # choose the one with most life
  352.             return ChooseMostLife (entity1name, entity2name)
  353.         # Second entity is only one to see the enemy
  354.         return CHOOSE_SECOND
  355.  
  356.     elif not p2.CanISee(enemy):
  357.         # First entity is only one to see the enemy
  358.         return CHOOSE_FIRST
  359.  
  360.     # This far means neither are group fighters and both are in combat 
  361.     # and both can see the enemy
  362.     return ChooseMostLife (entity1name, entity2name)
  363. ##################################################################################
  364.  
  365.  
  366.  
  367. # Define the default NPC python person class
  368. class NPCPerson (Basic_Funcs.PlayerPerson):
  369.     InvestigatingSound = FALSE
  370.     SoundPriorities = [-1.0, -1.0, -1.0, -1.0, -1.0]
  371.     Asleep = FALSE
  372.     SleepYOffset = 1100.0        # this may need adjusting for non-knight chars
  373.     group_fighter=TRUE
  374.     group_leader=TRUE
  375.     AttackingNPC=FALSE
  376.     goto_limit2aa=TRUE
  377.     imusic_noseen_warp=0
  378.     DelayNoSeenFuncMusicBackUp=0
  379.     last_insulting_time_1AA=-1
  380.     LastThrownHurtTime=0
  381.     AttacksOwnKind=FALSE
  382.     AttackNPCTime = 5
  383.     Angry=FALSE
  384.     Furious=FALSE
  385.     ChanceOfFuryOnHurt = 0.00
  386.     ChanceOfFuryOnLeaderDeath = 0.00
  387.     ImpatientAttackTime= 5.0
  388.  
  389.  
  390.     def __init__(self, me):
  391.         Basic_Funcs.PlayerPerson.__init__(self, me)
  392.         self.SoundPriorities = [-1.0, -1.0, -1.0, -1.0, -1.0]
  393.         self.inheritance = 1
  394.  
  395.         #_________________________________________#
  396.         #  Record some personal data              #
  397.         #_________________________________________#
  398.         AddMyWatchAnims(me.Name)
  399.         self.NPC = 1
  400.  
  401.  
  402.         #pdb.set_trace()    
  403.         self.ResetCombat(me.Name)
  404.         self.NoFXOnHit= FALSE
  405.         
  406.         
  407.         #_________________________________________#
  408.         # Initialise core                         #
  409.         #_________________________________________#
  410.         me.SubscribeToList("Listeners")
  411.         me.Deaf = 0
  412.         me.CombatGroup = "Group of " + me.Name
  413.  
  414.  
  415.         #_________________________________________#
  416.         # Set up the core functions               #
  417.         #_________________________________________#
  418.         me.SeeFunc=self.StdSeeTheEnemy
  419.         me.HearFunc=self.StdHearFunc
  420.         me.DelayNoSeenFunc=self.StdDelayNoSeen
  421.         me.NoAllowedAreaFunc=self.StdNoAllowedArea
  422.         me.EnemyNoAllowedAreaFunc=self.StdEnemyNoAllowedArea
  423.         me.ImHurtFunc=self.StdImHurt
  424.         me.ImDeadFunc=self.StdImDead
  425.         me.EnemyDeadFunc=self.StdEnemyDead
  426.         me.AnmEndedFunc=self.StdAnmEnded
  427.         me.EnterCloseFunc=self.StdEnterClose
  428.         me.EnterLargeFunc=self.StdEnterLarge
  429.         me.EnterPrimaryAAFunc=self.StdEnterPrimaryAA
  430.         me.EnterSecondaryAAFunc=self.StdEnterSecondaryAA
  431.         me.CharSeeingEnemyFunc=self.StdCharSeeingEnemy         
  432.         me.ToggleCombatFunc=self.StdToggleCombat         
  433.  
  434.         # Set us up to start in the large range, so archers get your bows out!
  435.         #pdb.set_trace()
  436.         self.WeaponsOut(me.Name)
  437.  
  438.     #_________________________________________#
  439.     # Define our functions                    #
  440.     #_________________________________________#
  441.     
  442.     def ResetCombat (self,EntityName):
  443.         me = Bladex.GetEntity(EntityName)
  444.         if me and me.Life>0:
  445.             me.BlockingPropensity = 0.5
  446.             me.AttackList = []
  447.             me.CombatDistFlag = not self.group_fighter
  448.  
  449.         self.AttacksOwnKind=FALSE
  450.         self.AttackNPCTime = 5
  451.         self.Angry=FALSE
  452.         self.Furious=FALSE
  453.         self.ChanceOfFuryOnHurt = 0.00
  454.         self.ChanceOfFuryOnLeaderDeath = 0.00
  455.         self.ImpatientAttackTime= 5.0
  456.  
  457.     def StopNPCsAttacking (self,EntityName):
  458.         #print EntityName+" should stop attacking enemy now "+`Bladex.GetTime()`
  459.         # Stop both combatants
  460.         me = Bladex.GetEntity(EntityName)
  461.         if me and me.Life>0:
  462.             enemy = Bladex.GetEntity(me.GetEnemyName())
  463.             self.StopAttackingNPC (EntityName)
  464.             if enemy and enemy.Life > 0 and enemy.Data.NPC:
  465.                 enemy.Data.StopAttackingNPC (enemy.Name)
  466.         
  467.  
  468.  
  469.     def StopAttackingNPC (self,EntityName):
  470.         if self.AttackingNPC:
  471.             me = Bladex.GetEntity(EntityName)
  472.             if me and me.Life>0:
  473.                 enemy = Bladex.GetEntity(me.GetEnemyName())
  474.                 if not enemy or enemy.Data.NPC:
  475.                     enemy = Bladex.GetEntity("Player1")
  476.                     if not enemy:
  477.                         print EntityName+": Cannot access handle to Player, in StopAttackingNPC()"
  478.                         Bladex.AddScheduledFunc(Bladex.GetTime() + self.AttackNPCTime, self.StopNPCsAttacking,(EntityName,))
  479.                         return
  480.                     #print EntityName+": Stopping attacking "+me.GetEnemyName()+" at time: "+`Bladex.GetTime()`
  481.                     Damage.DropInvalidObjectsOnImpact (EntityName)
  482.                     me.Wuea=Reference.WUEA_ENDED
  483.                     me.InterruptCombat()
  484.                     if me.SetEnemy(enemy):
  485.                         self.AttackingNPC=FALSE
  486.                         MaxCombatDist = Bladex.GetCharType(me.CharType,me.CharTypeExt).MaxCombatDist
  487.                         if me.SQDistance2(enemy) < (MaxCombatDist*MaxCombatDist) or me.CanISee(enemy):
  488.                             me.SetActiveEnemy(enemy)
  489.                             me.Chase(enemy, me.ActionAreaMax)
  490.                             if me.GetActionMode()==ROUTE_CHASE and self.IsArcher():
  491.                                 self.Switch2MeleeWeapons(EntityName)
  492.                         else:
  493.                             me.LaunchWatch()
  494.                             Damage.DropInvalidObjectsOnImpact (EntityName)
  495.                             me.Wuea=Reference.WUEA_ENDED
  496.                             me.LaunchAnmType("attack_look",1)
  497.                         self.CheckToJoin (EntityName)
  498.                     else:
  499.                         print EntityName+": Cannot SetEnemy to Player, in StopAttackingNPC()"
  500.                         Bladex.AddScheduledFunc(Bladex.GetTime() + self.AttackNPCTime, self.StopNPCsAttacking,(EntityName,))
  501.                         return
  502.  
  503.     #
  504.     # Standard function of ending a route
  505.     #
  506.     def StdRouteEnded(self,EntityName):        
  507.         pass
  508.             
  509.  
  510.     #
  511.     # Standard function of ending a chase without combat
  512.     #
  513.     def StdEndChase(self,EntityName):
  514.         me = Bladex.GetEntity(EntityName)
  515.         # Check I'm not dead        
  516.         if me and me.Life >0:
  517.             if not me.InCombat:
  518.                 Reference.debugprint(EntityName + ": I have ended a chase without combat (StdEndChase1)")
  519.                 enemy_pos=me.EnemyLastSeen
  520.                 if Actions.IsFacingPos(EntityName, enemy_pos[0], enemy_pos[2]):
  521.                     self.StdEndChase2(EntityName)
  522.                 else:
  523.                     Actions.TurnToFacePos(EntityName, enemy_pos[0], enemy_pos[2])
  524.                     me.RouteEndedFunc=self.StdEndChase2        # Continue when we're facing
  525.  
  526.  
  527.     def StdEndChase2(self,EntityName):
  528.         me = Bladex.GetEntity(EntityName)
  529.         # Check I'm not dead
  530.         if me and me.Life > 0:
  531.             Reference.debugprint(EntityName + ": I have ended a chase without combat (StdEndChase2)")
  532.             me.RouteEndedFunc=self.StdRouteEnded
  533.             me.StopLooking()
  534.             self.InvestigatingSound = FALSE
  535.             enemy=Bladex.GetEntity(me.GetEnemyName())
  536.             enemy_in_sight = enemy and me.CanISee(enemy)
  537.             if enemy_in_sight and enemy.InsideActionArea(me.ActionAreaMax):
  538.                 if Actions.IsFacingEntity(EntityName, me.GetEnemyName()):
  539.                     self.LaunchMyWatch (EntityName)
  540.                 else:
  541.                     Actions.TurnToFaceEntity(EntityName, me.GetEnemyName())
  542.                     me.RouteEndedFunc=self.LaunchMyWatch
  543.             else:        
  544.                 if enemy_in_sight:
  545.                     self.StdSeeEnemyUnreachable (EntityName)
  546.                 else:
  547.                     Damage.DropInvalidObjectsOnImpact (EntityName)
  548.                     me.Wuea=Reference.WUEA_ENDED
  549.                     if me.GetActionMode() != ROUTE_WATCH:
  550.                         self.LaunchMyWatch (EntityName)
  551.                     me.LaunchAnmType("look_around",1)
  552.                 # The enemy has disappeared for us around here
  553.                 # If we cannot find him, change our behaviour from the standard no seen function
  554.                 me.DelayNoSeenFunc=self.EndChaseDelayNoSeen
  555.                 if me.Data.imusic_noseen_warp==1:
  556.                     DMusic.RestoreMusicWarperDelayNoSeenFunc(EntityName)
  557.  
  558.     def PutMeToSleep(self,EntityName):
  559.         if not self.Asleep:
  560.             me = Bladex.GetEntity(EntityName)
  561.             me.SetTmpAnmFlags(1,1,0,0,1,1) 
  562.             # doesn't work for the traitor knight, so just call the Tkn version instead!
  563.             #We need to move the char down as well to touch the floor
  564.             me.Position = (me.Position[0], me.Position[1]+self.SleepYOffset, me.Position[2])
  565.             me.LaunchAnimation("Tkn_sleep")
  566.             me.Blind=1  #just in case
  567.             self.Asleep = TRUE
  568.  
  569.     def WakeMeUp(self,EntityName):
  570.         if self.Asleep:
  571.             me = Bladex.GetEntity(EntityName)
  572.             me.Blind=0  #just in case
  573.             # alert animation
  574.             me.Position = (me.Position[0], me.Position[1]-(self.SleepYOffset*0.5), me.Position[2])
  575.             if me.AnimName[:5] == "Sleep" or me.AnimName[:5] == "sleep":
  576.                 me.Wuea=Reference.WUEA_ENDED
  577.                 me.LaunchAnmType("alarm01",1)
  578.             self.Asleep = FALSE
  579.  
  580.     #  
  581.     # Standard function of trying to initialise a chase, 
  582.     #
  583.     def StdStartChase(self,EntityName):
  584.         me = Bladex.GetEntity(EntityName)
  585.         enemy=Bladex.GetEntity(me.GetEnemyName())
  586.         me.AnmEndedFunc=self.StdAnmEnded
  587.         #enemy_pos=enemy.Position
  588.         #me.StartLooking(enemy_pos[0], enemy_pos[1], enemy_pos[2])
  589.         if enemy.InsideActionArea(me.ActionAreaMax) or (self.IsArcher() and me.InsideActionArea(me.ActionAreaMax)):
  590.             self.StdStartChase2 (EntityName)
  591.         else:
  592.             # The following is to turn to face the enemy when we are already at an illegal border
  593.             self.StdSeeEnemyUnreachable (EntityName)
  594.  
  595.     def StdSeeEnemyUnreachable(self,EntityName,check1aaTo2aa=1):
  596.         me = Bladex.GetEntity(EntityName)
  597.         Reference.debugprint(EntityName + ": Enemy Unreachable")
  598.         if Bladex.GetTime()-self.LastThrownHurtTime<THROWNHURTTIME_GAP:
  599.             return
  600.                 
  601.         if me.InsideActionArea(me.ActionAreaMin) and (check1aaTo2aa and not me.Will1aaTo2aa):
  602.  
  603.             if me.Data.goto_limit2aa:
  604.                 back_area_min=me.ActionAreaMin
  605.                 back_area_max=me.ActionAreaMax
  606.                 me.ActionAreaMin=0
  607.                 me.ActionAreaMax=0
  608.                 enemy=Bladex.GetEntity(me.GetEnemyName())
  609.                 des_pos=enemy.Position
  610.                 me.GoToJogging=1
  611.                 if me.GoTo(des_pos[0],des_pos[1],des_pos[2]):
  612.                     me.ActionAreaMin=back_area_min
  613.                     me.ActionAreaMax=back_area_max
  614.                 else: 
  615.                     Reference.debugprint(EntityName + ": GoTo enemy_pos not working, with action area 0!")
  616.                     me.ActionAreaMin=back_area_min
  617.                     me.ActionAreaMax=back_area_max
  618.  
  619.  
  620.             return
  621.  
  622.         elif me.InsideActionArea(me.ActionAreaMin):
  623.             if me.GetActionMode() != ROUTE_WATCH:
  624.                 self.LaunchMyWatch (EntityName)
  625.             if not Actions.IsFacingEntity(EntityName, me.GetEnemyName()):
  626.                 Actions.TurnToFaceEntity(EntityName, me.GetEnemyName())
  627.             else:
  628.                 curr_time=Bladex.GetTime()
  629.                 if curr_time-self.last_insulting_time_1AA>4:
  630.                     insult_prob=whrandom.uniform(0.0, 1.0)
  631.                     if insult_prob<0.8:
  632.                         Combat.Insult(EntityName)
  633.                     insult_var=whrandom.uniform(-2.0, 1.0)
  634.                     self.last_insulting_time_1AA=Bladex.GetTime()+insult_var
  635.         else:
  636.             back_area_min=me.ActionAreaMin
  637.             back_area_max=me.ActionAreaMax
  638.             me.ActionAreaMax= 0
  639.             me.ActionAreaMin= 0
  640.             
  641.             init_pos=me.InitPos
  642.             me.InvertedRoute=1 # Move backwards
  643.             if me.GoTo(init_pos[0],init_pos[1],init_pos[2]):
  644.                 me.ActionAreaMin=back_area_min
  645.                 me.ActionAreaMax=back_area_max
  646.             else:
  647.                 Reference.debugprint(EntityName + ": GoTo init_pos not working, with action area 0!")
  648.                 me.ActionAreaMin=back_area_min
  649.                 me.ActionAreaMax=back_area_max
  650.             
  651.  
  652.     def StdStartChase2(self,EntityName):
  653.         me = Bladex.GetEntity(EntityName)
  654.         enemy=Bladex.GetEntity(me.GetEnemyName())
  655.         oldActionMode = me.GetActionMode()        
  656.         if (oldActionMode == ROUTE_WATCH) or (oldActionMode == ROUTE_BOWING):
  657.             # We could have got here after turning, so reset the RouteEndedFunc.
  658.             me.RouteEndedFunc=self.StdRouteEnded
  659.         if oldActionMode == ROUTE_CHASE:
  660.             pass
  661.         else:
  662.             self.ResetCombat(EntityName)
  663.             last_time_seen=me.LastTimeSeen       #Note that the "Chase" function updates the LastSeenTime!
  664.             me.Chase(enemy, me.ActionAreaMax)
  665.             if me.GetActionMode()==ROUTE_CHASE:
  666.                 if self.IsArcher():
  667.                     self.Switch2MeleeWeapons(EntityName)
  668.                 else:
  669.                     if Bladex.GetTime()-last_time_seen>40 or last_time_seen<0:
  670.                         me.LaunchAnmType("alarm01",1)
  671.                     #else:
  672.                     #    print "Too early to alarm..." + str(me.LastTimeSeen)
  673.  
  674.                 self.InvestigatingSound = FALSE
  675.                 me.RouteEndedFunc=self.StdEndChase 
  676.                 if me.Aim or Actions.CurrentlyBowing(EntityName):
  677.                     me.Wuea=Reference.WUEA_ENDED
  678.                     Actions.EndBowMode(EntityName)
  679.             else:
  680.                 self.StdChaseFailed (EntityName, oldActionMode)
  681.  
  682.  
  683.     # Is Chase() going to put us in BOWING mode when it fails
  684.     def IsArcher(self):                            # Needs to more sopisticated when inventory is working
  685.         return Actions.StatL(self.Name)==Actions.RA_BOW
  686.         
  687.  
  688.     def StdChaseFailed(self,EntityName, oldActionMode):    # Try to restore our state to whatever we were doing before attempting to chase    
  689.         me = Bladex.GetEntity(EntityName)
  690.         newActionMode = me.GetActionMode()
  691.         if newActionMode == ROUTE_BOWING:
  692.             Reference.debugprint(EntityName + ": I cannot start a chase so I will bow")    
  693.             pass
  694.         #NOTA : R_WATCH incluye _BAY (al fallar un GoTo desde una W_BAY se pasa AUTOMATICAMEnTE a watch!!!)
  695.         elif oldActionMode == ROUTE_WATCH:
  696.             Reference.debugprint(EntityName + ": I cannot start a chase so I will watch again")
  697.             self.LaunchMyWatch(EntityName)
  698.  
  699.             enemy=Bladex.GetEntity(me.GetEnemyName())
  700.             if enemy and me.CanISee(enemy) and me.InsideActionArea(me.ActionAreaMin):
  701.                 inv = me.GetInventory()
  702.                 if inv.HasBow and me.RangeActive:
  703.                     #print "StdChaseFailed-> Just facing due to carry bow"
  704.                     enemy_pos=me.EnemyLastSeen
  705.                     if not Actions.IsFacingPos(EntityName, enemy_pos[0], enemy_pos[2]):
  706.                         Actions.TurnToFacePos(EntityName, enemy_pos[0], enemy_pos[2])
  707.                 else:
  708.                     self.StdSeeEnemyUnreachable (EntityName,0)
  709.  
  710.         
  711.  
  712.     def GiveOrders (self, EntityName):
  713.         me=Bladex.GetEntity(EntityName)
  714.         if me and me.Life>0 and self.NextOrdersTo and self.NextOrders:
  715.             me.Wuea=Reference.WUEA_ENDED
  716.             me.SetTmpAnmFlags(1,0,1,0,1,1) 
  717.             me.LaunchAnmType("order",1)
  718.             me.AnmEndedFunc=self.GiveOrders2
  719.  
  720.     def GiveOrders2 (self, EntityName):
  721.         me=Bladex.GetEntity(EntityName)
  722.         if me and self.NextOrdersTo and self.NextOrders:
  723.             for name in self.NextOrdersTo:
  724.                 self.NextOrders(name)
  725.  
  726.     def CheckToJoin (self, EntityName):
  727.         ##startmem = BDAux.GetAvailablePhysicalMemory()
  728.         me = Bladex.GetEntity(EntityName)
  729.         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  730.         ##    pdb.set_trace()
  731.         # Get a list of the enemies of my enemy currently in combat
  732.         #pdb.set_trace()
  733.         ally_list = me.GetCombatants()
  734.         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  735.         ##    pdb.set_trace()
  736.         for ally_name in ally_list:
  737.             if ally_name != EntityName:    # Cannot really happen I think
  738.                 ally = Bladex.GetEntity (ally_name)
  739.                 if ally:
  740.                     if me.CombatGroup != ally.CombatGroup:
  741.                         self.JoinGroup (EntityName, ally.CombatGroup)
  742.                     return
  743.         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  744.         ##    pdb.set_trace()
  745.  
  746.         self.CheckGoodGroupFormation (EntityName, TRUE)        
  747.         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  748.         ##    pdb.set_trace()
  749.  
  750.     def JoinGroup (self, EntityName, GroupName):
  751.         me = Bladex.GetEntity(EntityName)
  752.         # Joining Group Logic
  753.         me.CombatGroup = GroupName
  754.         self.group_fighter = FALSE
  755.         self.group_leader  = FALSE
  756.         if not self.Furious:
  757.             me.CombatDistFlag = 1        # move out
  758.         self.CheckGoodGroupFormation (EntityName, TRUE)
  759.  
  760.     def LeaveGroup(self, EntityName):
  761.         # Make sure the group we are leaving has a fighter and a leader
  762.         me = Bladex.GetEntity(EntityName)
  763.         if self.group_fighter or self.group_leader:
  764.             self.SetGroupFormation(EntityName, FALSE, self.group_leader)
  765.         NewCombatGroup = "Group of " + me.Name
  766.         if me.CombatGroup == NewCombatGroup:
  767.             NewCombatGroup= NewCombatGroup + '... Splitters'
  768.         me.CombatGroup = NewCombatGroup
  769.         self.group_leader = TRUE
  770.         self.group_fighter = TRUE
  771.  
  772.  
  773.     #
  774.     # Standard function of seeing an enemy 
  775.     #
  776.     def StdSeeTheEnemy(self,EntityName):
  777.         me = Bladex.GetEntity(EntityName)
  778.         Reference.debugprint (EntityName + ": I see the enemy");
  779.         life = me.Life
  780.         if life > 0.0:        # Check I'm not dead
  781.             if me.Blind==1:
  782.                 pass
  783.             else:
  784.                 me.LookAtEntity(me.GetEnemyName())
  785.                 
  786.                 #Just in case we were doing a wait animation
  787.                 if me.GetActionMode() == ROUTE_BAY:    
  788.                     me.Wuea=Reference.WUEA_ENDED
  789.  
  790.                 self.CheckToJoin(EntityName)
  791.                 if me.GetActionMode()!=ROUTE_CHASE:
  792.                     self.StdStartChase(EntityName)
  793.                 
  794.                 if me.GetActionMode()==ROUTE_BOWING: 
  795.                     if self.AimPressed:
  796.                         angle= Reference.TARGET_ANGLE_MAX- me.Accuracy*(Reference.TARGET_ANGLE_MAX-Reference.TARGET_ANGLE_MIN)
  797.                         if me.AimOffTarget<angle:
  798.                             print "Releasing Arrow"
  799.                             Actions.TestReleaseArrow(EntityName)
  800.                     else: 
  801.                         if me.Wuea!=Reference.WUEA_WAIT:
  802.                             print "Drawing Bow"
  803.                             Actions.TestDrawBow (EntityName)
  804.                 elif me.Aim or Actions.CurrentlyBowing(EntityName):
  805.                     me.Wuea=Reference.WUEA_ENDED
  806.                     Actions.EndBowMode(EntityName)
  807.                     me.SetOnFloor()
  808.         else:
  809.             print (EntityName + ": Cannot get a handle on me")
  810.     #
  811.     # Standard function of hearing an enemy 
  812.     #
  813.     # make a default database here.  Other entities can have other databases...
  814.     # Sonidas Flechas (Arrow sounds)
  815.     # Objeto Arrojado o golpeado (thrown objects or hitting sounds)
  816.     # Sonido de enemigo.  Por grito o herida (Other NPCs shouting, or injured)
  817.     # Sonido de personaje ojando no esta en modo siglo (pisadas) (PC sounds when they're not walking silently -- footsteps)
  818.     # Gritas de atao o herida (Battle cries or injuries of the PC)
  819.  
  820.     def GetSoundType(self, SoundName):
  821.         if Reference.SoundTypes.has_key(SoundName):
  822.             return Reference.SoundTypes[SoundName][0]
  823.         return Reference.SND_UNCLASSIFIED
  824.         
  825.     def GetSoundPriority (self, EntityName,  SoundName, Volume):
  826.         me = Bladex.GetEntity(EntityName)
  827.         # Check against our sound tables
  828.         priority = Reference.SND_UNCLASSIFIED        # look this up in a dictionary for our race, or -1.0 if not present
  829.         sound_type= self.GetSoundType(SoundName)
  830.         if sound_type != Reference.SND_UNCLASSIFIED:
  831.             priority = self.SoundPriorities [sound_type]
  832.             # volume should be between 0.0 and 1.0 or an order of magnitude smaller 
  833.             # than the base priority.  Scale it down to be sure
  834.             return  priority + (Volume * 0.01)
  835.         
  836.     def IsSoundHigherPriority (self, EntityName, SoundName, Volume):
  837.         me = Bladex.GetEntity(EntityName)
  838.         priority = self.GetSoundPriority (EntityName, SoundName, Volume)
  839.         if priority <= 0.0:    # if we're not interested in this kind of sound:
  840.             return FALSE        
  841.         elif (not self.InvestigatingSound) or (me.GetActionMode()!=ROUTE_SINGLE):
  842.             return TRUE
  843.         else:
  844.             investigating_priority = self.GetSoundPriority (EntityName, self.InvestigatingSoundName, self.InvestigatingSoundVolume)
  845.             return priority > investigating_priority
  846.  
  847.     def StdInvestigateSound(self,EntityName):
  848.         me = Bladex.GetEntity(EntityName)
  849.  
  850.         if me and me.Life > 0:
  851.             me.StartLooking(self.InvestigatingSoundX, self.InvestigatingSoundY, self.InvestigatingSoundZ)
  852.             Reference.debugprint (EntityName + ": Im going to investigate "+self.InvestigatingSoundName+" at pos "+`self.InvestigatingSoundX`+", "+`self.InvestigatingSoundY`+", "+`self.InvestigatingSoundZ`);
  853.             me.GoToSneaking=1
  854.             me.GoTo(self.InvestigatingSoundX,self.InvestigatingSoundY,self.InvestigatingSoundZ)
  855.  
  856.             if me.AstarState<>ASTAR_SOLVED:
  857.                 # We cannot get there, just look at the source of the sound instead
  858.                 me.GoToSneaking=0
  859.                 if Actions.IsFacingPos(EntityName, self.InvestigatingSoundX, self.InvestigatingSoundZ):
  860.                     self.LaunchMyWatch (EntityName)
  861.                 else:
  862.                     Actions.TurnToFacePos(EntityName, self.InvestigatingSoundX, self.InvestigatingSoundZ)
  863.                     me.RouteEndedFunc=self.LaunchMyWatch
  864.             else:
  865.                 # We can use the same end func as ending a chase
  866.                 me.Heard = TRUE
  867.                 me.RouteEndedFunc=self.StdEndChase2
  868.  
  869.     def CanGoTo (self, EntityName, x, y, z):
  870.         me = Bladex.GetEntity(EntityName)
  871.         if me and me.Life > 0:
  872.             me.GoTo(x,y,z)
  873.             if me.AstarState==ASTAR_SOLVED:
  874.                 me.LaunchWatch()
  875.                 return TRUE
  876.         return FALSE
  877.  
  878.  
  879.     def StdHearFunc(self,EntityName, SoundName, x, y, z, Volume):
  880.         me = Bladex.GetEntity(EntityName)
  881.  
  882.         if me and Bladex.InsideActionArea(me.ActionAreaMax, x , y , z)==0:
  883.             #print "About to investigate a sound NO in AAs " + EntityName
  884.             return
  885.  
  886.  
  887.         if me and me.Life > 0 and me.Deaf<>1:
  888.  
  889. ##            try:
  890.                 # Is the sound below audible range
  891.                 if Volume < Bladex.GetCharType(me.CharType,me.CharTypeExt).HearMinVolume:
  892.                     return
  893.                 
  894.                 # No need to bother responding if we're already in combat
  895.                 if me.InCombat:
  896.                     return
  897.                 
  898.                 if DEBUG_SOUNDS:
  899.                     pdb.set_trace()
  900.                 sound_type= self.GetSoundType(SoundName)
  901.                 
  902.                 # Is the sound unknown
  903.                 if sound_type==Reference.SND_UNCLASSIFIED:
  904.                     return
  905.                 
  906.                 # If our enemy is dead, don't bother going to investigate
  907.                 enemy=Bladex.GetEntity(me.GetEnemyName())
  908.                 if (not enemy) or (not enemy.Person) or enemy.Life <= 0:
  909.                     return
  910.                     
  911.                 # for footsteps etc, Check they belong to the player, not realistic, but quick
  912.                 if sound_type==Reference.SND_NOISYPC:
  913.                     #if self.GroupCoveringPoint (EntityName, x, y, z, FALSE):
  914.                     #    return
  915.                     if enemy.LastSound != SoundName:
  916.                         return
  917.                     
  918.                     elsp= enemy.LastSoundPosition
  919.                     if elsp[0]!= x or elsp[1]!=y or elsp[2]!=z:
  920.                         return
  921.                 
  922.                 # Was the sound generated by oureself
  923.                 #if me.TestPosInOwnBox (x, y, z, 1.05):
  924.                 if me.LastSound==SoundName:
  925.                     lsp= me.LastSoundPosition
  926.                     if lsp[0]== x and lsp[1]==y and lsp[2]==z:
  927.                         return
  928.                 
  929.                 # Is the sound from our last thrown hurt ?
  930.                 if Bladex.GetTime()-self.LastThrownHurtTime<THROWNHURTTIME_GAP*0.5:
  931.                     return    
  932.                 
  933.                 # The see functions will take care of this
  934.                 if me.CanISee(enemy):
  935.                     return
  936.                     
  937.                 if self.Asleep:
  938.                     self.WakeMeUp(EntityName)
  939.  
  940.                 if me.GetActionMode() == ROUTE_BAY and me.CanGoTo(x,y,z)==0:
  941.                     #print "StdHearFunc, debug - BAY stuff..."
  942.                     return 
  943.  
  944.                 
  945.                 if self.group_leader:
  946.                     # record that we have dealt with the sound
  947.                     self.DealtWithSound= SoundName
  948.                     self.DealtWithSoundX= x
  949.                     self.DealtWithSoundY= y
  950.                     self.DealtWithSoundZ= z
  951.                     
  952.                     # Assign an investigator
  953.                     investigator = self.GetGroupFighter(EntityName)
  954.                     if (not investigator) or investigator.GetActionMode()==ROUTE_CHASE or investigator.InCombat:
  955.                         investigator = me
  956.                 else:
  957.                     group_leader = self.GetGroupLeader(EntityName)
  958.                     if group_leader and not (group_leader.InCombat or group_leader.GetActionMode()==ROUTE_CHASE):
  959.                         # does the leader know already?
  960.                         try:
  961.                             ldr_data= group_leader.Data
  962.                             if SoundName==ldr_data.DealtWithSound and x==ldr_data.DealtWithSoundX and y==ldr_data.DealtWithSoundY and z==ldr_data.DealtWithSoundZ:
  963.                                 return
  964.                         except:
  965.                             pass
  966.                         group_leader.HearFunc(group_leader.Name, SoundName, x, y, z, Volume)
  967.                         # leader will tell investigator what to do
  968.                         # but we can take the initiative to turn around
  969.                         if (not me.InCombat) and (me.GetActionMode()!=ROUTE_CHASE):
  970.                             if not Actions.IsFacingPos(EntityName, x, z):
  971.                                 Actions.QuickTurnToFacePos(EntityName, x, z)
  972.                         return
  973.                     else:
  974.                         # leader is busy, investigate ourself
  975.                         investigator = me
  976.     
  977.                 if investigator.Data.InvestigatingSound and SoundName == investigator.Data.InvestigatingSoundName and x == investigator.Data.InvestigatingSoundX and y == investigator.Data.InvestigatingSoundY and z == investigator.Data.InvestigatingSoundZ:
  978.                     # investigator is already investigating this sound        
  979.                     return 
  980.                 elif investigator.Data.IsSoundHigherPriority(investigator.Name, SoundName, Volume) and investigator.GetActionMode()!=ROUTE_CHASE and not investigator.InCombat:
  981.                     me.StartLooking(x, y, z)
  982.     
  983.                     # Turn to face the sound
  984.                     if not Actions.IsFacingPos(EntityName, x, z):
  985.                         Actions.QuickTurnToFacePos(EntityName, x, z)
  986.  
  987.  
  988.                     # React to the sound, with alarm
  989.                     if investigator.Name != EntityName: 
  990.                         # Tell investigator to turn to face the sound
  991.                         if not Actions.IsFacingPos(investigator.Name, x, z):
  992.                             Actions.QuickTurnToFacePos(investigator.Name, x, z)
  993.                         
  994.                         if (not investigator.Data.InvestigatingSound):
  995.                             if (me.AnimName[:4] != "hurt" and me.AnimName[:5] != "sleep"):
  996.                                 if investigator.Data.CanGoTo(investigator.Name, x, y, z):
  997.                                     me.Wuea=Reference.WUEA_ENDED
  998.                                     me.SetTmpAnmFlags(1,0,1,0,1,1) 
  999.                                     me.LaunchAnmType("alarm01",1)
  1000.     
  1001.                     # Send off fighter to investigate
  1002.                     investigator.Data.InvestigatingSound = TRUE
  1003.                     investigator.Data.InvestigatingSoundName = SoundName
  1004.                     investigator.Data.InvestigatingSoundVolume = Volume
  1005.                     investigator.Data.InvestigatingSoundX = x
  1006.                     investigator.Data.InvestigatingSoundY = y
  1007.                     investigator.Data.InvestigatingSoundZ = z
  1008.     
  1009.                     if me.AnimName=="alarm01":
  1010.                         if EntityName != investigator.Name:
  1011.                             self.NextOrdersTo = []
  1012.                             self.NextOrdersTo.append(investigator.Name)
  1013.                             self.NextOrders = investigator.Data.StdInvestigateSound
  1014.                             me.AnmEndedFunc=self.GiveOrders
  1015.                         else:
  1016.                             me.AnmEndedFunc=self.StdInvestigateSound
  1017.                     else:
  1018.                         if EntityName != investigator.Name:
  1019.                             self.NextOrdersTo = []
  1020.                             self.NextOrdersTo.append(investigator.Name)
  1021.                             self.NextOrders = investigator.Data.StdInvestigateSound
  1022.                             self.GiveOrders (EntityName)
  1023.                         else:
  1024.                             self.StdInvestigateSound (EntityName)
  1025. ##            except TypeError,detail:
  1026. ##                print "TypeError Exception",detail
  1027. ##                pdb.set_trace()
  1028.  
  1029.  
  1030.     #
  1031.     # Aux funcs
  1032.     #
  1033.  
  1034.     def LaunchMyWatch(self,EntityName):
  1035.         me = Bladex.GetEntity(EntityName)
  1036.         if me and me.Life > 0:
  1037.             enemy=Bladex.GetEntity(me.GetEnemyName())
  1038.             if not enemy or not me.CanISee(enemy):
  1039.                 me.StopLooking()
  1040.  
  1041.             #Just in case . This is the best place 4 this
  1042.             me.GoToJogging=0
  1043.             me.GoToSneaking=0
  1044.  
  1045.             me.LaunchWatch()
  1046.  
  1047.  
  1048.     def Turn180AndWatch(self,EntityName):
  1049.         me = Bladex.GetEntity(EntityName)
  1050.         Actions.Turn180(EntityName)
  1051.         me.RouteEndedFunc=self.LaunchMyWatch
  1052.  
  1053.     def LaunchMyPatrol(self,EntityName):
  1054.         me = Bladex.GetEntity(EntityName)
  1055.         me.StopLooking()
  1056.  
  1057.         init_pos=me.InitPos
  1058.         my_pos=me.Position
  1059.         x = init_pos[0] - my_pos[0]
  1060.         z = init_pos[2] - my_pos[2]
  1061.         DiscountDistance = 1000.0  #Used 2b 500
  1062.         if (not me.InsideActionArea(me.ActionAreaMin)) or (x*x+z*z)>(DiscountDistance*DiscountDistance):
  1063.             me.GoTo(init_pos[0],init_pos[1],init_pos[2])
  1064.             Reference.debugprint(EntityName+": Going 2 InitPos - self.LaunchMyPatrol")
  1065.             me.RouteEndedFunc=self.Turn180AndWatch
  1066.         else:
  1067.             Reference.debugprint(EntityName+": Not back2init cause quite close and inside MinAA")
  1068.             pass
  1069.         
  1070.     #
  1071.     # Standard function of what to do when the enemy is out of sight for some time 
  1072.     #
  1073.     def StdDelayNoSeen(self,EntityName):
  1074.         ##startmem = BDAux.GetAvailablePhysicalMemory()
  1075.         me = Bladex.GetEntity(EntityName)
  1076.         # Check I'm not dead
  1077.         if me.Life > 0:
  1078.             if (not self.Asleep) and (not me.Blind):
  1079.                 ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1080.                 ##    pdb.set_trace()
  1081.  
  1082.                 if me.Aim or Actions.CurrentlyBowing(EntityName):
  1083.                     me.Wuea=Reference.WUEA_ENDED
  1084.                     Actions.EndBowMode(EntityName)
  1085.                     me.SetOnFloor()
  1086.  
  1087.                 Reference.debugprint(EntityName+": Im in StdDelayNoSeen")
  1088.                 #self.SetGroupFormation (EntityName, TRUE, FALSE)
  1089.                 ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1090.                 ##    pdb.set_trace()
  1091.  
  1092.                 me.StopLooking()
  1093.                 enemy_name=me.GetEnemyName()
  1094.                 ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1095.                 ##    pdb.set_trace()
  1096.  
  1097.                 enemy=Bladex.GetEntity(enemy_name)
  1098.                 ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1099.                 ##    pdb.set_trace()
  1100.                 
  1101.                 if me.GetActionMode() != ROUTE_CHASE:
  1102.                     if me.GetActionMode() != ROUTE_SINGLE and me.GetActionMode() != ROUTE_BAY:
  1103.                         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1104.                         ##    pdb.set_trace()
  1105.  
  1106.                         Reference.debugprint(EntityName+": I am not chasing")
  1107.                         self.LaunchMyPatrol(EntityName)
  1108.                         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1109.                         ##    pdb.set_trace()
  1110.  
  1111.                 else:
  1112.                     Reference.debugprint(EntityName+": I am chasing")
  1113.                     if me.AstarState<>ASTAR_SOLVED:
  1114.                         # Face enemy as much as possible
  1115.                         lastseenpos = me.EnemyLastSeen
  1116.                         me.StartLooking(lastseenpos[0], lastseenpos[1], lastseenpos[2])
  1117.                         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1118.                         ##    pdb.set_trace()
  1119.  
  1120.                         if Actions.IsFacingPos(EntityName, lastseenpos[0], lastseenpos[2]):
  1121.                             self.LaunchMyWatch (EntityName)
  1122.                             ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1123.                             ##    pdb.set_trace()
  1124.  
  1125.                         else:
  1126.                             Actions.TurnToFacePos(EntityName, lastseenpos[0], lastseenpos[2])
  1127.                             me.RouteEndedFunc=self.LaunchMyWatch
  1128.                             ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1129.                             ##    pdb.set_trace()
  1130.  
  1131.         ##if BDAux.GetAvailablePhysicalMemory() != startmem:
  1132.         ##    pdb.set_trace()
  1133.  
  1134.     #
  1135.     # Alternate function if we've just ended a chase and the enemy is out of sight for some time
  1136.     #
  1137.     def EndChaseDelayNoSeen(self,EntityName):
  1138.         me = Bladex.GetEntity(EntityName)
  1139.         Reference.debugprint(EntityName + ": Im in EndChaseDelayNoSeen!")
  1140.         # Check I'm not dead
  1141.         if me.Life > 0:
  1142.             me.DelayNoSeenFunc=self.StdDelayNoSeen
  1143.             self.StdDelayNoSeen(EntityName)
  1144.             if me.Data.imusic_noseen_warp==1:
  1145.                 DMusic.RestoreMusicWarperDelayNoSeenFunc(EntityName)
  1146.  
  1147.  
  1148.     #
  1149.     # Standard function for entering a non allowed area (see the "Action Areas" thing)
  1150.     #
  1151.     def StdNoAllowedArea(self,EntityName):
  1152.         me = Bladex.GetEntity(EntityName)
  1153.         Reference.debugprint(EntityName + ": Im entering non-allowed area!")
  1154.         back_area_min=me.ActionAreaMin
  1155.         back_area_max=me.ActionAreaMax
  1156.         me.ActionAreaMin=0
  1157.         me.ActionAreaMax=0
  1158.         init_pos=me.InitPos
  1159.         me.InvertedRoute=0
  1160.         if me.GoTo(init_pos[0],init_pos[1],init_pos[2]):
  1161.             me.ActionAreaMin=back_area_min
  1162.             me.ActionAreaMax=back_area_max
  1163.         
  1164.  
  1165.     #
  1166.     # Standard function for when the enemy BEING CHASED (imp!) enters a non allowed area
  1167.     #
  1168.     def StdEnemyNoAllowedArea(self,EntityName):
  1169.         me = Bladex.GetEntity(EntityName)
  1170.         enemy=Bladex.GetEntity(me.GetEnemyName())
  1171.         
  1172.         if me.GetActionMode()<>ROUTE_CHASE:
  1173.             return
  1174.  
  1175.         init_pos=me.InitPos
  1176.         if (not me.InsideActionArea(me.ActionAreaMin)) and me.InsideActionArea(me.ActionAreaMax):
  1177.             me.InvertedRoute=1
  1178.         else:
  1179.             me.InvertedRoute=0
  1180.         me.GoTo(init_pos[0],init_pos[1],init_pos[2])
  1181.         Reference.debugprint(EntityName + ": My enemy has entered a non-allowed area")
  1182.  
  1183.     #
  1184.     # Standard function for taking injury
  1185.     #
  1186.     def StdImHurt(self,EntityName):
  1187.         Reference.debugprint(EntityName+": Oh! That hurt.")
  1188.         me = Bladex.GetEntity(EntityName)
  1189.         #
  1190.         # Rest of stuff
  1191.         #
  1192.         if self.NPC==0:
  1193.             return
  1194.  
  1195.         if self.Asleep:
  1196.             self.WakeMeUp(EntityName)
  1197.  
  1198.         #if me.GetActionMode() == ROUTE_WATCH:
  1199.         #    print "See due2 being hurt"
  1200.         #    me.SeeFunc(EntityName)
  1201.  
  1202.  
  1203.     #
  1204.     # Combat Group Functions
  1205.     #
  1206.     def GroupCoveringPoint (self, EntityName, x, y, z, include_me=TRUE):
  1207.         me = Bladex.GetEntity(EntityName)
  1208.         if me.CombatGroup:
  1209.             memberlist = me.GetGroupMembers()
  1210.             for member_name in memberlist:
  1211.                 if include_me or member_name != EntityName:
  1212.                     member = Bladex.GetEntity (member_name)
  1213.                     if member.TestPosInOwnBox (x, y, z, 1.05):
  1214.                         return TRUE
  1215.         elif include_me:
  1216.             return me.TestPosInOwnBox (x, y, z, 1.05)
  1217.         return FALSE
  1218.     
  1219.     def GetGroupLeader (self, EntityName):
  1220.         me = Bladex.GetEntity(EntityName)
  1221.         if me.CombatGroup:
  1222.             memberlist = me.GetGroupMembers()
  1223.             for member_name in memberlist:
  1224.                 member = Bladex.GetEntity (member_name)
  1225.                 if member and member.Life > 0 and member.Data.group_leader:
  1226.                     return member
  1227.         return None
  1228.  
  1229.     def GetGroupFighter (self, EntityName):
  1230.         me = Bladex.GetEntity(EntityName)
  1231.         if me.CombatGroup:
  1232.             memberlist = me.GetGroupMembers()
  1233.             for member_name in memberlist:
  1234.                 member = Bladex.GetEntity (member_name)
  1235.                 if member and member.Life > 0 and member.Data.group_fighter:
  1236.                     return member
  1237.         return None
  1238.  
  1239.  
  1240.     def CheckGoodGroupFormation(self,EntityName, include_me):
  1241.         me = Bladex.GetEntity(EntityName)
  1242.  
  1243.         if me.CombatGroup:
  1244.             memberlist = me.GetGroupMembers()
  1245.             if len(memberlist) > 1:
  1246.                 fighter_found = None
  1247.                 leader_found = None
  1248.                 enemy=Bladex.GetEntity(me.GetEnemyName())
  1249.                 for member_name in memberlist:
  1250.                     if include_me or member_name != EntityName:
  1251.                         member = Bladex.GetEntity (member_name)
  1252.  
  1253.                         if (not leader_found) and member and member.Data.group_leader and member.Life > 0:
  1254.                             if (not member.Data.group_fighter) and (not member.Data.Furious):
  1255.                                 member.CombatDistFlag = 1
  1256.                             leader_found = member.Name
  1257.                         else:
  1258.                             member.Data.group_leader = FALSE
  1259.  
  1260.                         if (not fighter_found) and member and member.Data.group_fighter and member.Life > 0 and enemy and member.CanISee(enemy):
  1261.                             member.CombatDistFlag = 0
  1262.                             fighter_found = member.Name
  1263.                         else:
  1264.                             if member.Data.group_fighter:
  1265.                                 if not member.Data.Furious:
  1266.                                     member.CombatDistFlag = 1
  1267.                                 member.Data.group_fighter = FALSE
  1268.  
  1269.                 if fighter_found and leader_found and (fighter_found != leader_found):
  1270.                     return
  1271.  
  1272.                 # If we get to this point then we're either missing a group leader or a group fighter
  1273.                 self.SetGroupFormation (EntityName, include_me, not leader_found)
  1274.     
  1275.             else:
  1276.                 if include_me:
  1277.                     self.group_leader= TRUE
  1278.                     self.group_fighter= TRUE
  1279.                     me.CombatDistFlag= 0
  1280.                 return
  1281.  
  1282.     def CallGroupMemberFunc(self,EntityName, func, include_me):
  1283.         me = Bladex.GetEntity(EntityName)
  1284.         if me and me.Life >0 and me.CombatGroup:
  1285.             memberlist = me.GetGroupMembers()
  1286.             if (not include_me) and memberlist.count(EntityName) > 0:
  1287.                 memberlist.remove(EntityName)
  1288.             for member_name in memberlist:
  1289.                 func (member_name)
  1290.  
  1291.     def SetNoGroupFighter(self,EntityName):    
  1292.         me = Bladex.GetEntity(EntityName)
  1293.         if me.CombatGroup:
  1294.             memberlist = me.GetGroupMembers()
  1295.             for member_name in memberlist:
  1296.                 member = Bladex.GetEntity (member_name)
  1297.                 if not member.Data.Furious:
  1298.                     member.CombatDistFlag = 1
  1299.                 member.Data.group_fighter = FALSE
  1300.  
  1301.     def SetNoGroupLeader(self,EntityName):    
  1302.         me = Bladex.GetEntity(EntityName)
  1303.         if me.CombatGroup:
  1304.             memberlist = me.GetGroupMembers()
  1305.             for member_name in memberlist:
  1306.                 member = Bladex.GetEntity (member_name)
  1307.                 member.Data.group_leader = FALSE
  1308.  
  1309.     def SetGroupFormation(self,EntityName, include_me, new_leader_needed):    
  1310.         if new_leader_needed:
  1311.             self.SetGroupLeader (EntityName, include_me)
  1312.         self.SetGroupFighter (EntityName, include_me)
  1313.  
  1314.     def SetGroupFighter(self,EntityName, include_me):
  1315.         me = Bladex.GetEntity(EntityName)
  1316.         if me.CombatGroup:
  1317.             self.SetNoGroupFighter (EntityName)
  1318.             # Can I find someone else to go in close range        
  1319.             memberlist = me.GetGroupMembers()
  1320.             if (not include_me) and memberlist.count(EntityName) > 0:
  1321.                 memberlist.remove(EntityName)
  1322.  
  1323.             if len(memberlist) > 0:
  1324.                 memberlist.sort(ChooseFighter)
  1325.                 member = Bladex.GetEntity (memberlist[0])
  1326.                 if member and member.Life > 0:
  1327.                     member.CombatDistFlag = 0    # move in
  1328.                     member.Data.group_fighter = TRUE
  1329.  
  1330.     def SetGroupLeader(self,EntityName, include_me):
  1331.         me = Bladex.GetEntity(EntityName)
  1332.         if me.CombatGroup:
  1333.             self.SetNoGroupLeader (EntityName)
  1334.             # Can I find someone else to go in close range
  1335.             memberlist = me.GetGroupMembers()
  1336.             if (not include_me) and memberlist.count(EntityName) > 0:
  1337.                 memberlist.remove(EntityName)
  1338.  
  1339.             if len(memberlist) > 0:
  1340.                 memberlist.sort(ChooseLeader)
  1341.                 member = Bladex.GetEntity (memberlist[0])
  1342.                 if member and member.Life>0:
  1343.                     member.Data.group_leader = TRUE
  1344.  
  1345.     def Respond2Thrown(self, EntityName, AttackerName):
  1346.         me = Bladex.GetEntity(EntityName)
  1347.         if AttackerName:
  1348.             enemy=Bladex.GetEntity(me.GetEnemyName())
  1349.             if enemy and not enemy.InsideActionArea(me.ActionAreaMax):
  1350.                 self.LastThrownHurtTime=Bladex.GetTime()
  1351.                 init_pos=me.InitPos
  1352.                 me.InvertedRoute=0 #Just in case
  1353.                 me.GoToJogging=1
  1354.                 if me.GoTo(init_pos[0],init_pos[1],init_pos[2]):
  1355.                     me.RouteEndedFunc= self.Turn180AndWatch
  1356.             else:
  1357.                 if me.GetActionMode() == ROUTE_WATCH:
  1358.                     #print "FIX?"
  1359.                     Actions.QuickTurnToFaceEntity(EntityName,AttackerName)
  1360.                 else:
  1361.                     print "Respond2Thrown->Bug?"
  1362.  
  1363.  
  1364.     def RespondToHit(self, EntityName, AttackerName, DamagePoints, DamageType, DamageZone, Shielded):
  1365.         # launch appropriate hurt anim
  1366.         Basic_Funcs.PlayerPerson.RespondToHit(self, EntityName, AttackerName, DamagePoints, DamageType, DamageZone, Shielded)
  1367.         
  1368.         if AttackerName and AttackerName != 'BWorld' and AttackerName != EntityName:
  1369.             me = Bladex.GetEntity(EntityName)
  1370.             if me and me.Life > 0:
  1371.                 # consider getting furious
  1372.                 chartype = Bladex.GetCharType(me.CharType,me.CharTypeExt)
  1373.                 if me.Life <= CharStats.GetCharMaxLife(me.Kind, me.Level)*0.25 and whrandom.random() < self.ChanceOfFuryOnHurt:
  1374.                     self.GetFurious (EntityName)
  1375.                 # consider attacking attacker back
  1376.                 damage_factor = DamagePoints / (me.Life+DamagePoints)
  1377.                 if damage_factor > me.Data.DamageFactorNone:
  1378.                     # Only if I'm still alive... Death events handled apart
  1379.                     Reference.debugprint(EntityName+": Im being attacked by "+AttackerName)
  1380.                     if AttackerName != me.GetEnemyName():
  1381.                         Reference.debugprint(EntityName+": " + AttackerName +" is not my enemy!" )
  1382.                         attacker = Bladex.GetEntity(AttackerName)
  1383.                         if attacker and (self.AttacksOwnKind or attacker.Kind != me.Kind):
  1384.                             Reference.debugprint(EntityName+": I will attack back")
  1385.                             # Only attack NPCs if not already, otherwise we get multiple scheduled funcs
  1386.                             if (not attacker.Data.NPC) or (not self.AttackingNPC):
  1387.                                 Reference.debugprint("attacker.Data.NPC: "+ `attacker.Data.NPC`+ ", self.AttackingNPC: " + `self.AttackingNPC`)
  1388.                                 # Interrupt whatever we were doing before
  1389.                                 Damage.DropInvalidObjectsOnImpact (EntityName)
  1390.                                 me.Wuea=Reference.WUEA_ENDED
  1391.                                 me.InterruptCombat()
  1392.                                 
  1393.                                 # Set up the new enemy, and start chasing him to be sure
  1394.                                 #print EntityName+": Starting attacking "+attacker.Name+" at time: "+`Bladex.GetTime()`
  1395.                                 me.SetEnemy(attacker)
  1396.                                 me.SetActiveEnemy(attacker)
  1397.                                 me.Chase(attacker, me.ActionAreaMax)
  1398.                                 if me.GetActionMode()==ROUTE_CHASE and self.IsArcher():
  1399.                                     self.Switch2MeleeWeapons(EntityName)
  1400.                                 
  1401.                                 
  1402.                                 #if not me.CanISee(attacker):
  1403.                                 #    me.Wuea=Reference.WUEA_ENDED
  1404.                                 #    me.LaunchAnmType("attack_look",1)
  1405.                                 
  1406.                                 # If its another NPC, we should make the switch from the PC temporary
  1407.                                 if attacker.Data.NPC:
  1408.                                     #pdb.set_trace()
  1409.                                     self.AttackingNPC=TRUE
  1410.                                     Bladex.AddScheduledFunc(Bladex.GetTime() + self.AttackNPCTime, self.StopNPCsAttacking,(EntityName,))
  1411.                                     if me.CombatGroup == attacker.CombatGroup:
  1412.                                         self.LeaveGroup (EntityName)
  1413.                                         self.CheckToJoin (EntityName)
  1414.                                         return
  1415.                     if me.CombatGroup and self.group_fighter and me.Life > 0:    # I am in close range
  1416.                         self.SetGroupFormation (EntityName, TRUE, FALSE)
  1417.  
  1418.  
  1419.     def HitFunc (self, EntityName, WeaponName, Cx, Cy, Cz, DirX, DirY, DirZ,wcx,wcy,wcz,wdx,wdy,wdz):
  1420.         me= Bladex.GetEntity(EntityName)
  1421.         if me and me.Life>0:
  1422.             if not me.InCombat:
  1423.                 
  1424.                 #x= pos[0]-DirX*1000.0
  1425.                 #z= pos[2]-DirZ*1000.0
  1426.                 
  1427.                 weapon= Bladex.GetEntity (WeaponName)
  1428.                 if weapon and weapon.Parent:
  1429.                     if not Actions.IsFacingEntity(EntityName, weapon.Parent):
  1430.                         Actions.QuickTurnToFaceEntity(EntityName, WeaponName)
  1431.                 else:
  1432.                     pos= me.Position
  1433.                     x= pos[0]+(Cx-pos[0])*1000.0
  1434.                     z= pos[2]+(Cz-pos[2])*1000.0
  1435.                     if not Actions.IsFacingPos(EntityName, x, z):
  1436.                         Actions.QuickTurnToFacePos(EntityName, x, z)
  1437.  
  1438.         Basic_Funcs.PlayerPerson.HitFunc (self, EntityName, WeaponName, Cx, Cy, Cz, DirX, DirY, DirZ,wcx,wcy,wcz,wdx,wdy,wdz)
  1439.  
  1440.  
  1441.     #
  1442.     # Standard function for dying
  1443.     #
  1444.  
  1445.         
  1446.     def StdImDead(self,EntityName):
  1447.         global TwinkleObjs
  1448.         Reference.debugprint(EntityName+": I died!")
  1449.         Basic_Funcs.PlayerPerson.PCImDead(self, EntityName)        
  1450.         
  1451.         me = Bladex.GetEntity(EntityName)
  1452.         if me.Life > 0:
  1453.             print EntityName + ': Warning! dead func when Life > 0!'
  1454.  
  1455.         DMusic.InformDead(EntityName)
  1456.         
  1457.         me.RemoveFromList("Listeners")
  1458.         #pdb.set_trace()
  1459.         me.AddAnmEventFunc("UnlinkAll", self.UnlinkAll)
  1460.         if self.Asleep:
  1461.             me.Wuea=Reference.WUEA_ENDED
  1462.             me.LaunchAnmType("sleep_wall_d")
  1463.             Reference.debugprint(EntityName+": Uuurgh! I died in my sleep!")
  1464.  
  1465.         if self.group_leader:
  1466.             memberlist = me.GetGroupMembers()
  1467.             if EntityName in memberlist:
  1468.                 memberlist.remove(EntityName)
  1469.             if len(memberlist) == 1:
  1470.                 # Chance that remaining member gets furious
  1471.                 #pdb.set_trace()
  1472.                 member = Bladex.GetEntity(memberlist[0])
  1473.                 if member and member.Life > 0:
  1474.                     enemy=Bladex.GetEntity(member.GetEnemyName()) 
  1475.                     if member.SQDistance2(enemy) > 3000*3000 or not Actions.IsFacingEntity(enemy.Name, member.Name):
  1476.                         if whrandom.random() < self.ChanceOfFuryOnLeaderDeath:
  1477.                             member.Data.GetFurious (member.Name)
  1478.  
  1479.         self.CheckGoodGroupFormation (EntityName, FALSE)
  1480.         self.CallGroupMemberFunc(EntityName, Combat.GetAngry, FALSE)
  1481.         
  1482.         me.RemoveFromList(me.CombatGroup)
  1483.  
  1484.         csound=Bladex.GetEntity(EntityName+"ContinuosSound")
  1485.         if csound:
  1486.             csound.StopSound()
  1487.             csound.SubscribeToList("Pin")
  1488.  
  1489.  
  1490.         # Drop the weapons if possible
  1491.  
  1492.         try:
  1493.             object = Bladex.GetEntity(me.InvLeft)
  1494.             if me.InvLeft and object and not object.TestHit:
  1495.                 Actions.RemoveFromInventory (me, object,"DropLeftEvent")
  1496.                 object.Alpha=1.0
  1497.                 object.Impulse(0.0, 0.0, 0.0) 
  1498.         except AttributeError: 
  1499.             pdb.set_trace()
  1500.         
  1501.         try:
  1502.             object = Bladex.GetEntity(me.InvRight)
  1503.             if me.InvRight and object and not object.TestHit:
  1504.                 Actions.RemoveFromInventory (me, object,"DropRightEvent")
  1505.                 object.Alpha=1.0
  1506.                 object.Impulse(0.0, 0.0, 0.0) 
  1507.         except AttributeError: 
  1508.             pdb.set_trace()
  1509.             
  1510.         # Drop everything else
  1511.         inv = me.GetInventory()
  1512.         #pdb.set_trace()
  1513.         while inv.nObjects > 0:
  1514.             object_name = inv.GetObject(0)
  1515.             object = Bladex.GetEntity(object_name)
  1516.             if object:
  1517.                 object.Position=me.Position
  1518.                 me.Unlink(object)
  1519.                 inv.RemoveObject(object_name)
  1520.                 object.ExcludeHitFor(me)
  1521.                 if object.Kind in TwinkleObjs:
  1522.                     Bladex.AddScheduledFunc(Bladex.GetTime(), Actions.TakeObject,("Player1",object_name))
  1523.                 else:    
  1524.                     if object.TestHit:
  1525.                         print "WARNING OBJECT "+object.Name+" REMOVED FROM WORLD BECAUSE COLLIDING"
  1526.                         object.RemoveFromWorld()
  1527.                     else:
  1528.                         object.Alpha=1.0
  1529.                         object.Impulse(0.0, 0.0, 0.0)
  1530.  
  1531.         while inv.nWeapons > 0:
  1532.             object_name = inv.GetWeapon(0)
  1533.             object = Bladex.GetEntity(object_name)
  1534.             if object:
  1535.                 object.Position=me.Position
  1536.                 me.Unlink(object)
  1537.                 inv.RemoveWeapon(object_name)
  1538.                 object.ExcludeHitFor(me)
  1539.                 try:
  1540.                     if object.TestHit:
  1541.                         object.RemoveFromWorld()
  1542.                     else:
  1543.                         object.Alpha=1.0
  1544.                         object.Impulse(0.0, 0.0, 0.0) 
  1545.                 except AttributeError:
  1546.                     print "TestHit unsupported for object "+object.Name
  1547.                     pdb.set_trace()
  1548.  
  1549.         while inv.nShields > 0:
  1550.             object_name = inv.GetShield(0)
  1551.             object = Bladex.GetEntity(object_name)
  1552.             if object:
  1553.                 object.Position=me.Position
  1554.                 me.Unlink(object)
  1555.                 inv.RemoveShield(object_name)
  1556.                 object.ExcludeHitFor(me)
  1557.                 if object.TestHit:
  1558.                     object.RemoveFromWorld()
  1559.                 else:
  1560.                     object.Alpha=1.0
  1561.                     object.Impulse(0.0, 0.0, 0.0) 
  1562.         
  1563.         while inv.nQuivers > 0:
  1564.             object_name = inv.GetQuiver(0)
  1565.             object = Bladex.GetEntity(object_name)
  1566.             if object:
  1567.                 object.Position=me.Position
  1568.                 me.Unlink(object)
  1569.                 inv.RemoveQuiver(object_name)
  1570.                 object.ExcludeHitFor(me)
  1571.                 if object.TestHit:
  1572.                     object.RemoveFromWorld()
  1573.                 else:
  1574.                     object.Alpha=1.0
  1575.                     object.Impulse(0.0, 0.0, 0.0) 
  1576.  
  1577.         while inv.nKeys > 0:
  1578.             object_name = inv.GetKey(0)
  1579.             object = Bladex.GetEntity(object_name)
  1580.             if object: 
  1581.                 object.Position=me.Position
  1582.                 me.Unlink(object)
  1583.                 inv.RemoveKey(object_name)
  1584.                 object.ExcludeHitFor(me)
  1585.                 Bladex.AddScheduledFunc(Bladex.GetTime(), Actions.TakeObject,("Player1",object_name))
  1586.                 
  1587.                 char = Bladex.GetEntity("Player1")
  1588.                 new_key_sound.Stop()
  1589.                 new_key_sound.PlayStereo()
  1590.                 #new_key_sound.Play(char.Position[0],char.Position[1],char.Position[2],0);
  1591.                 
  1592.                     
  1593.  
  1594.     #
  1595.     # Standard function for the enemies' death
  1596.     #
  1597.     def StdEnemyDead(self,EntityName):
  1598.         me = Bladex.GetEntity(EntityName)
  1599.         # Check I'm not dead        
  1600.         if me:
  1601.             if me.Life > 0 and (me.GetActionMode()==ROUTE_CHASE or me.InCombat):
  1602.                 me.DelayNoSeenFunc=self.StdDelayNoSeen
  1603.                 if me.Data.imusic_noseen_warp==1:
  1604.                     DMusic.RestoreMusicWarperDelayNoSeenFunc(EntityName)
  1605.  
  1606.                 self.InvestigatingSound = FALSE
  1607.                 self.LaunchMyWatch(EntityName)
  1608.                 Reference.debugprint(EntityName+": My enemy is dead.He he ! - py")
  1609.             
  1610.  
  1611.     def GetFurious (self, EntityName):
  1612.         me=Bladex.GetEntity(EntityName)
  1613.         
  1614.         if me and self.Furious == 0:        
  1615.             Reference.debugprint(EntityName + ": Getting Furious")
  1616.             self.Furious = 1
  1617.             me.BlockingPropensity = 0
  1618.  
  1619.             # Save the first attack
  1620.             movelist = me.AttackList
  1621.             first_attack = None
  1622.             for move in movelist:
  1623.                 if move[0]==Combat.ATTACK:
  1624.                     first_attack = move
  1625.                     break
  1626.             me.AttackList=filter(Combat.DoneInFury,me.AttackList)
  1627.             if first_attack:
  1628.                 first_attack[1]=1.00
  1629.                 me.AttackList.insert(0, first_attack)
  1630.  
  1631.             me.CombatDistFlag = 0
  1632.             Damage.DropInvalidObjectsOnImpact (EntityName)
  1633.             me.Wuea=Reference.WUEA_ENDED
  1634.             me.InterruptCombat()
  1635.             me.LaunchAnmType("fury",1)
  1636.             FuryTime=30.0
  1637.             Bladex.AddScheduledFunc(Bladex.GetTime() + FuryTime, self.ResetCombat,(EntityName,))
  1638.  
  1639.     #
  1640.     # Standard function for end of animation
  1641.     # It is set to null when finish!
  1642.     #
  1643.     def StdAnmEnded(self,EntityName):
  1644.         pass
  1645.         Reference.debugprint(EntityName+": Anm ended - py ")
  1646.  
  1647.     #
  1648.     # Standard function for entering close range combat 
  1649.     # Called only when CHASING an enemy !
  1650.     #
  1651.     def StdEnterClose(self,EntityName):
  1652.         Reference.debugprint(EntityName+": I am entering close combat")
  1653.         #pdb.set_trace()        
  1654.         me = Bladex.GetEntity(EntityName)
  1655.         # Check I'm not dead
  1656.         if me and me.Life > 0:
  1657.             self.SetGroupFormation (EntityName, TRUE, FALSE)
  1658.             self.Switch2MeleeWeapons (EntityName)
  1659.         
  1660.                     
  1661.     def Switch2MeleeWeapons(self,EntityName):
  1662.         me = Bladex.GetEntity(EntityName)
  1663.         if me and me.Life > 0 and not me.RangeActive:
  1664.             inv= me.GetInventory()
  1665.             right_type= Reference.GiveObjectFlag(me.InvRight)
  1666.                         
  1667.             # Do we have an item in the hand we can fight with            
  1668.             if inv.HoldingBow or not (right_type== Reference.OBJ_STANDARD or right_type== Reference.OBJ_WEAPON):
  1669.                 # Don't change if the enemy is unreachable
  1670.                 enemy=Bladex.GetEntity(me.GetEnemyName())
  1671.                 if me.AstarState!=ASTAR_NOSOLVED:
  1672.                     me.SwitchTo1H()
  1673.                     weapon_name= inv.GetSelectedWeapon()
  1674.                     if weapon_name and (weapon_name != me.InvRight and weapon_name != me.InvLeft):
  1675.                         # Launch the swap weapons animation
  1676.                         out= ScorerActions.CB_WeaponOutX(EntityName,0)
  1677.                         if not out:
  1678.                             me.AnmEndedFunc= ScorerActions.CB_WeaponOutX
  1679.                         Bladex.AddScheduledFunc(Bladex.GetTime()+2.0, self.Switch2MeleeWeapons,(EntityName,),EntityName+"ReSwitch2MeleeWeapons")
  1680.                 
  1681.                     Actions.EndBowMode(EntityName)
  1682.             
  1683.     def WeaponsOut(self,EntityName):
  1684.         me= Bladex.GetEntity(EntityName)
  1685.         if me.Life > 0:
  1686.             inv= me.GetInventory()
  1687.             if inv.HasBow:                
  1688.                 # Put quiver on back
  1689.                 des_quiver_name=inv.GetSelectedQuiver()
  1690.                 if des_quiver_name:
  1691.                     inv.LinkBack(des_quiver_name)
  1692.                     
  1693.                     # Put arrow in right
  1694.                     inv.LinkRightHand("None")
  1695.                     quiver=    Bladex.GetEntity(des_quiver_name)
  1696.                     if quiver and quiver.Data.NumberOfArrows() > 0:
  1697.                         arrow= quiver.Data.GiveArrow ()
  1698.                         inv.LinkRightHand(arrow.Name)
  1699.                                 
  1700.                         # Put bow in left
  1701.                         bow= inv.GetBow()
  1702.                         inv.LinkLeftHand(bow)
  1703.                         
  1704.                         return
  1705.                 
  1706.                 print "Enemy starting with bow, but without quiver/arrows"
  1707.             
  1708.             # Put sword in right
  1709.             if inv.nWeapons>0 and not me.InvRight:
  1710.                 weapon_name= inv.GetSelectedWeapon()
  1711.                 if not weapon_name:
  1712.                     weapon_name= inv.GetWeapon(0)
  1713.                 inv.LinkRightHand("None")
  1714.                 inv.LinkRightHand(weapon_name)
  1715.             
  1716.             # Put shield in left
  1717.             if inv.nShields>0 and not me.InvLeft:
  1718.                 shield_name= inv.GetSelectedShield()
  1719.                 if not shield_name:
  1720.                     shield_name= inv.GetShield(0)
  1721.                 inv.LinkLeftHand("None")
  1722.                 inv.LinkLeftHand(weapon_name)
  1723.     
  1724.         
  1725.     #
  1726.     # Standard function for entering large range combat 
  1727.     # Called only when CHASING an enemy !
  1728.     #                 
  1729.     def StdEnterLarge(self,EntityName):
  1730.         me = Bladex.GetEntity(EntityName)
  1731.         # Check I'm not dead        
  1732.         Reference.debugprint(EntityName + ": Im entering large area!")
  1733.         if me.Life > 0 and not me.MeleeActive:
  1734.             inv= me.GetInventory()
  1735.             if inv.HasBow:
  1736.                 left_type= Reference.GiveObjectFlag(me.InvLeft)
  1737.                 if left_type != Reference.OBJ_BOW:
  1738.                     me.SwitchToBow()
  1739.                     if inv.GetSelectedWeapon() != me.InvRight and inv.GetSelectedWeapon() != me.InvLeft:
  1740.                         # Launch the swap weapons animation
  1741.                         out= ScorerActions.CB_WeaponOutX(EntityName,0)
  1742.                         if not out:
  1743.                             me.AnmEndedFunc= ScorerActions.CB_WeaponOutX
  1744.                         Bladex.AddScheduledFunc(Bladex.GetTime()+2.0, self.StdEnterLarge,(EntityName,),EntityName+"ReStdEnterLarge")
  1745.  
  1746.     #
  1747.     # Standard function for entering PRIMARY AA
  1748.     #
  1749.     def StdEnterPrimaryAA(self,EntityName):
  1750.         me = Bladex.GetEntity(EntityName)
  1751.         Reference.debugprint(EntityName + ": Im entering primary area!")
  1752.         # Check I'm not dead
  1753.         if me.Life > 0:
  1754.             #NO -> Only called onlled once this function(...) !!!
  1755.             #if me.InvertedRoute==1 and not me.Will1aaTo2aa:
  1756.             if me.InvertedRoute==1:
  1757.                 self.LaunchMyWatch (EntityName)
  1758.                 me.LastTimeSeen=Bladex.GetTime()
  1759.             me.InvertedRoute=0 #Por si acaso
  1760.         
  1761.     
  1762.     #
  1763.     # Standard function for entering SECONDARY AA
  1764.     #                 
  1765.     def StdEnterSecondaryAA(self,EntityName):
  1766.         Reference.debugprint(EntityName + ": Im entering secondary area!")
  1767.         #print "StdEnterSecondaryAA"
  1768.         pass
  1769.             
  1770.  
  1771.     #
  1772.     # Standard function for when another character sees his enemy 
  1773.     # (...)
  1774.     #
  1775.     def StdCharSeeingEnemy(self,EntityName,EntityName2):    
  1776.         me = Bladex.GetEntity(EntityName)
  1777.         ally=Bladex.GetEntity(EntityName2)
  1778.  
  1779.         if me.CombatGroup==ally.CombatGroup:
  1780.             pass #Bob's grouping suff will do it
  1781.         # Check I'm not dead
  1782.         if me.Life > 0:
  1783.             #Reference.debugprint(EntityName + ": Im in StdCharSeeingEnemy with Char being " + EntityName2)
  1784.             
  1785.             if ally and me.CanISee(ally) and me.GetActionMode()<>ROUTE_CHASE:
  1786.                 if ally.GetActionMode()==ROUTE_CHASE and me.GetActionMode()<>ROUTE_CHASE:
  1787.                     me.SeeFunc(EntityName)
  1788.                 if ally.GetActionMode()==ROUTE_SINGLE and ally.Data.InvestigatingSound:
  1789.                     #Volume set to 1 , so he┤ll always hear it
  1790.                     self.StdHearFunc(EntityName,ally.Data.InvestigatingSoundName,ally.Data.InvestigatingSoundX,ally.Data.InvestigatingSoundY,ally.Data.InvestigatingSoundZ,1.0)
  1791.                     
  1792.             else:
  1793.                 pass
  1794.                 #Reference.debugprint(EntityName + ": I cannot see ally")
  1795.  
  1796.     #
  1797.     # Standard function for enggling on and off with an enemy
  1798.     # (...)
  1799.     #
  1800.     def StdToggleCombat(self,EntityName):
  1801.         import DMusic
  1802.         if self.NPC==1:
  1803.             DMusic.notifyCombat(EntityName)
  1804.  
  1805.     # Functions for loading and saving state
  1806.     def __save_core_funcs__(self):
  1807.         me = Bladex.GetEntity(self.Name)
  1808.         if not me:
  1809.             print "__save_core_funcs__() Warning: trying to save a non existent entity",self.Name
  1810.             return
  1811.  
  1812.         core_funcs = []
  1813.         j = 0
  1814.         funcs=[ ("SeeFunc",               self.StdSeeTheEnemy),
  1815.                 ("HearFunc",              self.StdHearFunc),
  1816.                 ("DelayNoSeenFunc",       self.StdDelayNoSeen),
  1817.                 ("NoAllowedAreaFunc",     self.StdNoAllowedArea),
  1818.                 ("EnemyNoAllowedAreaFunc",self.StdEnemyNoAllowedArea),
  1819.                 ("ImHurtFunc",            self.StdImHurt),
  1820.                 ("ImDeadFunc",            self.StdImDead),
  1821.                 ("EnemyDeadFunc",         self.StdEnemyDead),
  1822.                 ("AnmEndedFunc",          self.StdAnmEnded),
  1823.                 ("EnterCloseFunc",        self.StdEnterClose),
  1824.                 ("EnterLargeFunc",        self.StdEnterLarge),
  1825.                 ("EnterPrimaryAAFunc",    self.StdEnterPrimaryAA),
  1826.                 ("EnterSecondaryAAFunc",  self.StdEnterSecondaryAA),
  1827.                 ("CharSeeingEnemyFunc",   self.StdCharSeeingEnemy),
  1828.                 ("ToggleCombatFunc",      self.StdToggleCombat)]
  1829.  
  1830.         for i in funcs:
  1831.             exec('f = me.'+i[0])
  1832.             if (i[1] <> f):
  1833.                 print "Save Core Func para",me.Name," callback ",i[0]," funcion ", f
  1834.                 core_funcs.append((j,GameStateAux.SaveFunctionAux(f)))
  1835.             j = j + 1
  1836.  
  1837.         return(core_funcs)
  1838.  
  1839.     def __load_core_funcs__(self,param):
  1840.         me = Bladex.GetEntity(self.Name)
  1841.         if not me:
  1842.             print "__load_core_funcs__ -> Warning, trying to get a non existent entity",self.Name
  1843.             return
  1844.         
  1845.         funcs=[ "SeeFunc",
  1846.                 "HearFunc",
  1847.                 "DelayNoSeenFunc",
  1848.                 "NoAllowedAreaFunc",
  1849.                 "EnemyNoAllowedAreaFunc",
  1850.                 "ImHurtFunc",
  1851.                 "ImDeadFunc",
  1852.                 "EnemyDeadFunc",
  1853.                 "AnmEndedFunc",
  1854.                 "EnterCloseFunc",
  1855.                 "EnterLargeFunc",
  1856.                 "EnterPrimaryAAFunc",
  1857.                 "EnterSecondaryAAFunc",
  1858.                 "CharSeeingEnemyFunc",
  1859.                 "ToggleCombatFunc"]
  1860.  
  1861.         for i in param:
  1862. ##            try:
  1863.             print "Load Core Func ",i[1]," para ",me.Name," funcion ",funcs[i[0]]
  1864.             try:
  1865.                 GameStateAux.LoadFunctionAux(i[1],me,funcs[i[0]])
  1866.                 print "Loaded for entity"
  1867.             except:
  1868.                 GameStateAux.LoadFunctionAux(i[1],self,funcs[i[0]])
  1869.                 #assign_func=eval("obj."+method_name)
  1870.                 exec("me.%s=self.%s"%(funcs[i[0]],funcs[i[0]]))
  1871.                 print "Loaded for class"
  1872. ##            except Exception,exc:
  1873. ##                print "Exception in __load_core_funcs__ par ",me.Name,funcs[i[0]],i[1]
  1874. ##                print "Exception is",exc
  1875. ##                print i
  1876.  
  1877.     def __getstate__(self):
  1878.         # Tiene que devolver c≤mo poder guardar el estado de la clase
  1879.         PlayerPerson_state=Basic_Funcs.PlayerPerson.__getstate__(self)
  1880.         if(PlayerPerson_state[0]!=1):
  1881.             print "ERROR: NPCPerson.__getstate__(): Base class version differs."
  1882.             # Throw?
  1883.             return playerperson_state
  1884.         me=Bladex.GetEntity(self.Name)
  1885.         PlayerPerson_state[1]["NPCPerson"]=(self.InvestigatingSound,
  1886.                                       self.SoundPriorities,
  1887.                                       self.Asleep,
  1888.                                       self.SleepYOffset,
  1889.                                       self.group_fighter,
  1890.                                       self.group_leader,
  1891.                                       self.AttackingNPC,
  1892.                                       self.last_insulting_time_1AA,
  1893.                                       self.LastThrownHurtTime,
  1894.                                       self.AttacksOwnKind,
  1895.                                       self.AttackNPCTime,
  1896.                                       self.Angry,
  1897.                                       self.Furious,
  1898.                                       self.ChanceOfFuryOnHurt,
  1899.                                       self.ChanceOfFuryOnLeaderDeath,
  1900.                                       self.ImpatientAttackTime,
  1901.                                       self.goto_limit2aa,
  1902.                                       self.imusic_noseen_warp,
  1903.                                       self.DelayNoSeenFuncMusicBackUp,
  1904.                                       me.CombatGroup,
  1905.                                       self.__save_core_funcs__()
  1906.                                       )
  1907.         return PlayerPerson_state
  1908.  
  1909.     def __setstate__(self,parm):
  1910.         # Toma como parßmetro lo que devuelve __getstate__() y debe recrear la clase
  1911.         Basic_Funcs.PlayerPerson.__setstate__(self,parm)
  1912.  
  1913.         me=Bladex.GetEntity(self.Name)
  1914.         #_________________________________________#
  1915.         # Set up the core functions               #
  1916.         #_________________________________________#
  1917.         me.SeeFunc=self.StdSeeTheEnemy
  1918.         me.HearFunc=self.StdHearFunc
  1919.         me.DelayNoSeenFunc=self.StdDelayNoSeen
  1920.         me.NoAllowedAreaFunc=self.StdNoAllowedArea
  1921.         me.EnemyNoAllowedAreaFunc=self.StdEnemyNoAllowedArea
  1922.         me.ImHurtFunc=self.StdImHurt
  1923.         me.ImDeadFunc=self.StdImDead
  1924.         me.EnemyDeadFunc=self.StdEnemyDead
  1925.         me.AnmEndedFunc=self.StdAnmEnded
  1926.         me.EnterCloseFunc=self.StdEnterClose
  1927.         me.EnterLargeFunc=self.StdEnterLarge
  1928.         me.EnterPrimaryAAFunc=self.StdEnterPrimaryAA
  1929.         me.EnterSecondaryAAFunc=self.StdEnterSecondaryAA
  1930.         me.CharSeeingEnemyFunc=self.StdCharSeeingEnemy
  1931.         me.ToggleCombatFunc=self.StdToggleCombat
  1932.  
  1933.         self.inheritance = 1
  1934.  
  1935.         version=parm[0]
  1936.         if version==1:
  1937.             parms=parm[1]["NPCPerson"]
  1938.             self.InvestigatingSound=parms[0]
  1939.             self.SoundPriorities=parms[1]
  1940.             self.Asleep=parms[2]
  1941.             self.SleepYOffset=parms[3]
  1942.             self.group_fighter=parms[4]
  1943.             self.group_leader=parms[5]
  1944.             self.AttackingNPC=parms[6]
  1945.             self.last_insulting_time_1AA=parms[7]
  1946.             self.LastThrownHurtTime=parms[8]
  1947.             self.AttacksOwnKind=parms[9]
  1948.             self.AttackNPCTime=parms[10]
  1949.             self.Angry=parms[11]
  1950.             self.Furious=parms[12]
  1951.             self.ChanceOfFuryOnHurt=parms[13]
  1952.             self.ChanceOfFuryOnLeaderDeath=parms[14]
  1953.             self.ImpatientAttackTime=parms[15]
  1954.             self.goto_limit2aa=parms[16]
  1955.             self.imusic_noseen_warp=parms[17]
  1956.             self.DelayNoSeenFuncMusicBackUp=parms[18]
  1957.             me.CombatGroup=parms[19]
  1958.             self.__load_core_funcs__(parms[20])
  1959.         self.ResetCombat(self.Name)
  1960.         AddMyWatchAnims(self.Name)
  1961.         me=Bladex.GetEntity(self.Name)
  1962.  
  1963.         #Revisar estas 3, deberφan estar con las propiedades de la entidad.
  1964.         #me.BlockingPropensity = 0.5
  1965.         #me.AttackList = []
  1966.         me.CombatDistFlag = not self.group_fighter
  1967.         self.NoFXOnHit= FALSE
  1968.         self.WeaponsOut(self.Name)
  1969.  
  1970.  
  1971. def AddMyWatchAnims(EntityName):
  1972.     Reference.debugprint(EntityName + " adding WatchAnims")
  1973.     me = Bladex.GetEntity(EntityName)
  1974.     #me.AddWatchAnim("PATROL_LOOK_D")
  1975.     #me.AddWatchAnim("PATROL_LOOK_U")
  1976.     #me.AddWatchAnim("PATROL_LOOK_R")
  1977.     #me.AddWatchAnim("PATROL_LOOK_L")
  1978.  
  1979.  
  1980. ##############################################################
  1981. #    Clase base para caracteres estupidos, en principio       #
  1982. ##############################################################
  1983.  
  1984. #Nota: Se ira ampliando a medida que haga falta
  1985.  
  1986. class StupidNPCPerson (Basic_Funcs.PlayerPerson):
  1987.  
  1988.     InvestigatingSound = FALSE
  1989.     SoundPriorities = [-1.0, -1.0, -1.0, -1.0, -1.0]
  1990.  
  1991.     def __init__(self, me):
  1992.         Basic_Funcs.PlayerPerson.__init__(self, me)
  1993.  
  1994.         self.SoundPriorities = [-1.0, -1.0, -1.0, -1.0, -1.0]
  1995.         ###############################
  1996.         #  Record some personal data  #
  1997.         ###############################
  1998.  
  1999.         self.NPC = 1
  2000.  
  2001. #        self.Asleep = FALSE
  2002. #        self.SleepYOffset = 1100.0        # this may need adjusting for non-knight chars
  2003.  
  2004.         #####################
  2005.         #  Initialise core  #
  2006.         #####################
  2007.  
  2008.         me.SubscribeToList("Listeners")
  2009.         me.Deaf = 0
  2010.  
  2011.     def RespondToHit(self, EntityName, AttackerName, DamagePoints, DamageType, DamageZone, Shielded):
  2012.         pass
  2013.  
  2014.         ###############################
  2015.         #  Set up the core functions  #
  2016.         ###############################
  2017.  
  2018. #        me.SeeFunc=self.StdSeeTheEnemy
  2019. #        me.HearFunc=self.StdHearFunc
  2020. #        me.DelayNoSeenFunc=self.StdDelayNoSeen
  2021. #        me.NoAllowedAreaFunc=self.StdNoAllowedArea
  2022. #        me.EnemyNoAllowedAreaFunc=self.StdEnemyNoAllowedArea
  2023. #        me.ImHurtFunc=self.StdImHurt
  2024. #        me.ImDeadFunc=self.StdImDead
  2025. #        me.EnemyDeadFunc=self.StdEnemyDead
  2026. #        me.AnmEndedFunc=self.StdAnmEnded
  2027. #        me.EnterCloseFunc=self.StdEnterClose
  2028. #        me.EnterLargeFunc=self.StdEnterLarge
  2029. #        me.CharSeeingEnemyFunc=self.StdCharSeeingEnemy
  2030.  
  2031.  
  2032.     ##########################
  2033.     #  Define our functions  #
  2034.     ##########################
  2035.